package com.cskaoyan.service.impl;

import com.cskaoyan.bean.data.CartCheckedData;
import com.cskaoyan.bean.data.CartIndexData;
import com.cskaoyan.bean.vo.CartAddVo;
import com.cskaoyan.mapper.MarketCartMapper;
import com.cskaoyan.model.*;
import com.cskaoyan.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Author Pudding
 * @Date 2024/6/13 16:50
 */
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    MarketCartMapper cartMapper;
    @Autowired
    GoodsService goodsService;
    @Autowired
    GoodsProductService goodsProductService;
    @Autowired
    SystemService systemService;
    @Autowired
    AddressService addressService;
    @Autowired
    CouponUserService couponUserService;

    @Override
    public Integer goodsCount(Integer userId) {
        //1. 根据用户的id查询所有的购物车中的所有的记录
        List<MarketCart> marketCarts = this.getUserCartListByUserId(userId);

        //2. 通过流计算出购物车所有记录的总数
        int count = marketCarts.stream()
                .mapToInt(MarketCart::getNumber)
                .sum();

        return count;
    }

    @Override
    public List<MarketCart> getUserCartListByUserId(Integer userId) {
        //1. 根据用户的id查询所有的购物车中的所有的记录
        //1.1 构造查询条件
        MarketCartExample example = new MarketCartExample();
        example.createCriteria().andDeletedEqualTo(false)
                .andUserIdEqualTo(userId);
        example.setOrderByClause("add_time desc");
        //1.2 进行查询
        List<MarketCart> marketCarts = cartMapper.selectByExample(example);

        return marketCarts;
    }

    @Override
    public CartIndexData cartIndex(Integer userId) {
        //1. 根据userId查询购物车对应的记录
        List<MarketCart> userCartListByUserId = this.getUserCartListByUserId(userId);

        //2. 调用CartStat静态方法stat给当前用户购物车记录进行统计
        CartIndexData.CartStat stat = CartIndexData.CartStat.stat(userCartListByUserId);

        //3. 给购物车信息进行封装到CartIndexData对象，然后再作为响应的data
        CartIndexData cartIndexData = CartIndexData.builder()
                .cartList(userCartListByUserId)
                .cartTotal(stat)
                .build();

        return cartIndexData;
    }

    @Override
    public MarketCart findByPost(Integer userId, Integer goodsId, Integer productId) {
        //1. 构造查询条件
        MarketCartExample example = new MarketCartExample();
        example.createCriteria().andDeletedEqualTo(false)
                .andUserIdEqualTo(userId)
                .andGoodsIdEqualTo(goodsId)
                .andProductIdEqualTo(productId);

        //2. 进行查询
        List<MarketCart> marketCarts = cartMapper.selectByExample(example);

        //3. 返回结果
        return marketCarts != null && marketCarts.size() == 1 ? marketCarts.get(0) : null;
    }

    @Override
    public int create(Integer userId, CartAddVo cartAddVo) {
        //1. 根据goods_id和product_id获取商品表信息和商品货品表信息
        MarketGoods marketGoods = goodsService.findById(cartAddVo.getGoodsId());
        MarketGoodsProduct marketGoodsProduct = goodsProductService.findById(cartAddVo.getProductId());

        //2. 构造新的购物车订单
        MarketCart marketCart = MarketCart.builder()
                .userId(userId)
                .goodsId(cartAddVo.getGoodsId())
                .goodsSn(marketGoods.getGoodsSn())
                .goodsName(marketGoods.getName())
                .productId(cartAddVo.getProductId())
                .price(marketGoodsProduct.getPrice())
                .number(cartAddVo.getNumber())
                .specifications(marketGoodsProduct.getSpecifications())
                .addTime(new Date())
                .picUrl(marketGoods.getPicUrl())
                .updateTime(new Date())
                .deleted(false)
                .build();

        //3. 将该条记录添加到数据库
        return cartMapper.insertSelective(marketCart);
    }

    @Override
    public int modify(MarketCart updateCart) {
        //1. 按照传来的参数进行更新
        return cartMapper.updateByPrimaryKeySelective(updateCart);
    }

    @Override
    public int checked(Integer userId, CartCheckedData cartCheckedData) {
        //1.1 构成更新条件
        MarketCartExample example = new MarketCartExample();
        example.createCriteria().andDeletedEqualTo(false)
                .andUserIdEqualTo(userId)
                .andProductIdIn(cartCheckedData.getProductIds());

        //1.2 创建更新条件的对象，要更新的数据对象只有这个对象中非空的字段会被更新
        MarketCart marketCart = MarketCart.builder()
                .checked(cartCheckedData.getIsChecked())
                .updateTime(new Date())
                .build();

        //2. 进行条件更新
        return cartMapper.updateByExampleSelective(marketCart, example);
    }

    @Override
    public Map checkout(int userId, Map<String, Object> parameterMap) {

        /* 下面是响应报文的响应体中需要的参数：
         * actualPrice 真正价格
         * addressId 地址id
         * availableCouponLength 用户可用优惠劵数量
         * cartId 购物车列表id
         * checkedAddress 封装了选中的地址信息
         * checkedGoodsList 封装了选中的商品信息
         * couponId 优惠劵id
         * couponPrice 优惠金额
         * goodsTotalPrice 选中商品总价
         * grouponPrice (现阶段不考虑团购)
         * grouponRulesId (现阶段不考虑团购)
         * orderTotalPrice 订单总价
         * userCouponId userCoupon表的id
         * */

        /*
         *  传入形参里的parameterMap其实就是最后要返回的封装响应数据的map，
         *  由于在cartController的checkout方法中将前端的请求参数全部添加到了封装响应字段的map中
         *  所以在这里可以从这个parameterMap中获得前端的请求参数的值
         */
        //通过parameterMap获得请求参数cartId
        Integer cartId = Integer.parseInt(parameterMap.get("cartId").toString());
        //这个example用于查询通过购物车下单的商品
        MarketCartExample example = new MarketCartExample();
        //创建checkedGoodsList用于存储购物车选中的那些商品 或者 通过立即购买的商品
        List<MarketCart> checkedGoodsList = new ArrayList<>();
        if (cartId == 0) {
            //cartId为0 代表通过购物车下单
            //添加查询条件，选中的购物车记录，其中userId是隐含条件
            example.createCriteria().andUserIdEqualTo(userId)
                    .andDeletedEqualTo(false)
                    .andCheckedEqualTo(true);
            //调用selectByExample方法得到选中的商品，赋值给checkedGoodsList
            checkedGoodsList = cartMapper.selectByExample(example);
        } else {
            //cartId不为0 代表的是立即购买
            //直接通过查找cartId就可以得到立即购买的商品，同时赋值给checkedGoodsList
            checkedGoodsList.add(cartMapper.selectByPrimaryKey(cartId));
        }
        //将响应字段checkedGoodsList添加到封装响应数据的map中
        parameterMap.put("checkedGoodsList", checkedGoodsList);
        //得到请求参数中的addressId
        Integer addressId = Integer.parseInt(parameterMap.get("addressId").toString());
        //通过addressId(主键)查询到选择的地址
        MarketAddress checkedAddress = addressService.selectById(addressId);
        //将响应字段checkedAddress封装到map中
        parameterMap.put("checkedAddress", checkedAddress);
        if (checkedAddress != null)
            //如果address不是空值就把查询到的addressId添加到封装响应数据的map中，也就是覆盖掉了之前请求参数中的
            parameterMap.put("addressId", checkedAddress.getId());
        //获得请求参数中的couponId
        Integer couponId = Integer.parseInt(parameterMap.get("couponId").toString());
        //调用index方法得到indexMap，从其中获取一些响应字段中需要的信息
        Map indexMap = index(userId);
        //得到当前购物车中的所有商品信息
        Map cartTotalMap = (Map) indexMap.get("cartTotal");
        //获得所有选中的商品总价
        Object checkedGoodsAmount = cartTotalMap.get("checkedGoodsAmount");
        //转型
        BigDecimal goodsTotalPrice = new BigDecimal(String.valueOf(checkedGoodsAmount));
        //添加响应字段goodsTotalPrice(商品总价)到parameterMap
        parameterMap.put("goodsTotalPrice", goodsTotalPrice);
        //调用couponUserService的checkout方法得到封装了优惠劵id、用户可用优惠劵数量、优惠金额的result
        List result = couponUserService.checkout(userId, couponId, goodsTotalPrice);
        //从result中获得优惠金额
        BigDecimal couponPrice = (BigDecimal) result.get(2);
        //向parameterMap中存入用户可用优惠劵数量
        parameterMap.put("availableCouponLength", result.get(1));
        //向parameterMap中存入优惠金额(=满减金额)
        parameterMap.put("couponPrice", result.get(2));
        //向parameterMap中存入优惠劵id
        parameterMap.put("couponId", result.get(0));
        //调用systemService的toMap方法得到关于运费的配置信息
        Map<String, String> systemConfig = systemService.toMap();
        //从systemConfig中获得免运费的最小消费金额
        BigDecimal marketExpressFreightMin = new BigDecimal(systemConfig.get("market_express_freight_min"));
        //从systemConfig中获得运费值
        BigDecimal marketExpressFreightValue = new BigDecimal(systemConfig.get("market_express_freight_value"));
        //定义所支付运费，初值为0
        BigDecimal freightPrice = BigDecimal.valueOf(0);
        //判断商品总额是否满足免运费条件
        if (goodsTotalPrice.compareTo(marketExpressFreightMin) < 0) {
            //不满足条件就支付运费，需支付运费就是从systemConfig中得到的运费值
            freightPrice = marketExpressFreightValue;
        }
        //满足条件就不用支付运费，运费就是初值0
        //添加freightPrice(运费)到parameterMap中
        parameterMap.put("freightPrice", freightPrice);
        //最终金额为 商品总价+运费-优惠金额
        BigDecimal realPrice = goodsTotalPrice.add(freightPrice).subtract(couponPrice);
        //判断最终金额是否小于0(毕竟倒贴钱不合理)
        if (realPrice.compareTo(new BigDecimal(0)) < 0) {
            //如果小于0则将最终金额置0
            realPrice = new BigDecimal(0);
        }
        //添加订单总额，也就是最终金额(由于不考虑团购和用户积分减免)
        parameterMap.put("orderTotalPrice", realPrice);
        //添加真正价格，也就是最终金额(由于不考虑团购和用户积分减免)
        parameterMap.put("actualPrice", realPrice);
        //现阶段不考虑团购，先返回0
        parameterMap.put("grouponPrice", 0);
        //返回封装好的数据
        return parameterMap;
    }

    @Override
    public Map index(int userId) {
        //创建一个map用于封装响应字段
        Map<String, Object> map = new HashMap<>();
        //创建example用于查询
        MarketCartExample example = new MarketCartExample();
        //添加查询条件
        MarketCartExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false)
                .andUserIdEqualTo(userId);
        //根据userId查询购物车记录
        List<MarketCart> marketCarts = cartMapper.selectByExample(example);
        //封装响应字段cartList
        map.put("cartList", marketCarts);
        //创建cartTotalMap 用于存储响应字段cartTotal中的数据
        Map<String, Object> cartTotalMap = new HashMap<>();
//        if (marketCarts.isEmpty()) {
//            map.put("cartTotal", cartTotalMap);
//            return map;
//        }

        //通过stream(流)来获得购物车中的所有商品总价
        Optional<BigDecimal> goodsAmount = marketCarts.stream()
                .map(marketCart -> marketCart.getPrice().multiply(BigDecimal.valueOf(marketCart.getNumber())))
                .reduce(BigDecimal::add);
        //通过stream(流)来获得购物车中的所有商品总数
        Optional<Short> goodsCount = marketCarts.stream()
                .map(MarketCart::getNumber)
                .reduce((number1, number2) -> (short) (number1 + number2));
        //添加条件为选中的商品
        criteria.andCheckedEqualTo(true);
        //查询购物车中所有选中的商品记录，也可以通过流来做，这里采用条件查询
        List<MarketCart> checkedMarketCarts = cartMapper.selectByExample(example);
        //通过stream(流)来获得购物车中的所有选中商品总价
        Optional<BigDecimal> checkedGoodsAmount = checkedMarketCarts.stream()
                .map(checkedMarketCart -> checkedMarketCart.getPrice().multiply(BigDecimal.valueOf(checkedMarketCart.getNumber())))
                .reduce(BigDecimal::add);
        //通过stream(流)来获得购物车中的所有选中的商品总数
        Optional<Short> checkedGoodsCount = checkedMarketCarts.stream()
                .map(MarketCart::getNumber)
                .reduce((number1, number2) -> (short) (number1 + number2));
        //添加响应字段checkedGoodsAmount到map中
        cartTotalMap.put("checkedGoodsAmount", checkedGoodsAmount.isPresent() ? checkedGoodsAmount.get() : 0);
        //添加响应字段checkedGoodsCount到map中
        cartTotalMap.put("checkedGoodsCount", checkedGoodsCount.isPresent() ? checkedGoodsCount.get() : 0);
        //添加响应字段goodsAmount到map中
        cartTotalMap.put("goodsAmount", goodsAmount.isPresent() ? goodsAmount.get() : 0);
        //添加响应字段goodsCount到map中
        cartTotalMap.put("goodsCount", goodsCount.isPresent() ? goodsCount.get() : 0);
        //添加cartTotal字段到map中，其中cartTotalMap封装了cartTotal中的数据
        map.put("cartTotal", cartTotalMap);
        return map;
    }

    @Override
    public int deleteById(Integer userId, Integer goodsId, Integer productId) {
        //1. 构造删除条件
        MarketCartExample example = new MarketCartExample();
        example.createCriteria().andDeletedEqualTo(false)
                .andUserIdEqualTo(userId)
                .andGoodsIdEqualTo(goodsId)
                .andProductIdEqualTo(productId);

        //2. 进行删除
        return cartMapper.deleteByExample(example);
    }

    @Override
    public int updateNumber(Map map) {
        //1. 构造更新的对象非空字段
        //1.1 这里必须先判断一下类型为Integer，先转化为int，再转换为short就可以了，不能再builder中强转
        int number = (int) map.get("number");
        short num = ((short) number);

        MarketCart record = MarketCart.builder()
                .number(num)
                .build();

        //2. 构造查询条件
        MarketCartExample example = new MarketCartExample();
        example.createCriteria().andDeletedEqualTo(false)
                .andIdEqualTo((Integer) map.get("id"))
                .andGoodsIdEqualTo((Integer) map.get("goodsId"))
                .andProductIdEqualTo((Integer) map.get("productId"));
        //3. 进行查询
        return cartMapper.updateByExampleSelective(record, example);
    }

    @Override
    public int deleteByProductIds(Map<String,List<Integer>> map) {
        //1. 根据产品id删除对应购物中的商品
        //1.1 构造删除条件
        MarketCartExample example = new MarketCartExample();
        example.createCriteria().andDeletedEqualTo(false)
                .andProductIdIn(map.get("productIds"));

        //1.2 进行删除操作
        return cartMapper.deleteByExample(example);
    }

    /**
     * 查找 用户选定的所有 商品
     * @param userId
     * @return
     */
    @Override
    public List<MarketCart> findCheckedGoods(Integer userId) {
        MarketCartExample cartExample = new MarketCartExample();
        cartExample.createCriteria().andDeletedEqualTo(false).andUserIdEqualTo(userId).andCheckedEqualTo(true);

        List<MarketCart> marketCarts = cartMapper.selectByExample(cartExample);

        return marketCarts;
    }

    /**
     *
     * @param i
     * @param cartId
     * @return
     */
    @Override
    public MarketCart findByCartId(Integer cartId) {
        MarketCart marketCart = cartMapper.selectByPrimaryKey(cartId);
        return marketCart;
    }
}
